package com.loadburn.heron.storage.dao.impl;

import com.google.inject.Provider;
import com.loadburn.heron.storage.EntityStorage;
import com.loadburn.heron.storage.config.EntityMetadata;
import com.loadburn.heron.storage.sql.Page;
import com.loadburn.heron.storage.dao.BaseDao;
import com.loadburn.heron.storage.sql.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * @author slacrey (scstlinfeng@yahoo.com)
 *         Date: 13-12-25
 */
public class BaseDaoImpl<T> implements BaseDao<T> {

    private static final Logger logger = LoggerFactory.getLogger(BaseDaoImpl.class.getName());
    private Class<T> clazz;
    private final EntityStorage es;

    public BaseDaoImpl(Provider<EntityStorage> es, Class<T> clazz) {
        this.es = es.get();
        this.clazz = clazz;
    }

    public Class<T> getClazz() {
        return clazz;
    }

    public EntityStorage getEs() {
        return es;
    }

    @Override
    public boolean save(T object) throws SQLException {
        return es.save(object);
    }

    @Override
    public boolean remove(T object) throws SQLException {
        return es.remove(object);
    }

    @Override
    public boolean update(T object, Long primaryKey) throws SQLException {
        return es.update(object, primaryKey);
    }

    @Override
    public List<T> findAll() throws SQLException {
        return es.find(clazz);
    }

    @Override
    public List<T> findByQueryName(String name, Map<String, Object> nameParams) throws SQLException {
        return es.find(clazz, name, nameParams);
    }

    @Override
    public Page<T> paginateAll(Page<T> page) throws SQLException {
        return es.findPageable(clazz, page.getNumber(), page.getSize());
    }

    @Override
    public Page<T> paginateByQueryName(String name, Map<String, Object> nameParams, Page<T> page) throws SQLException {
        return es.findPageable(clazz, name, nameParams, page.getNumber(), page.getSize());
    }

    @Override
    public T findById(Long primaryKey) throws SQLException {
        return es.findOne(clazz, primaryKey);
    }

    @Override
    public void save(List<T> entities) throws SQLException {

        if (entities != null && !entities.isEmpty()) {
            for (T t : entities) {
                es.save(t);
            }
        }
    }

    @Override
    public void delete(List<? extends T> entities) throws SQLException {

        if (entities != null && !entities.isEmpty()) {
            for (T t : entities) {
                es.remove(t);
            }
        }
    }

    @Override
    public void deleteAll() throws SQLException {
        es.createNamedQuery(clazz, EntityMetadata.REMOVE_ALL_STATEMENT).executeUpdate();
    }

    @Override
    public long count() throws SQLException {
        Query query = es.createNamedQuery(clazz, EntityMetadata.COUNT_ALL_STATEMENT);
        return query.count();
    }

    @Override
    public long count(String name, Map<String, Object> nameParams) throws SQLException {
        Query query = es.createNamedQuery(clazz, name);
        query.setParameterNameMap(nameParams);
        return query.count();
    }
}
